#!/usr/bin/env python3
"""
直播监听工具主程序
这个脚本是应用程序的主入口点，负责启动GUI界面
"""
import sys
import os
import logging
import json
import traceback
from PyQt5.QtCore import QTimer
import time
import signal
import threading
import atexit
import locale
from typing import List, Dict, Any, Optional

# 设置系统默认编码为UTF-8，解决中文编码问题
if sys.platform.startswith('win'):
    # Windows平台特别容易出现编码问题
    import subprocess
    # 设置控制台代码页为UTF-8
    os.system('chcp 65001 > nul')
    # 设置环境变量
    os.environ['PYTHONIOENCODING'] = 'utf-8'

# 避免使用可能不兼容的方法设置编码
try:
    # Python 3.7+ 支持reconfigure
    if hasattr(sys.stdout, 'reconfigure'):
        sys.stdout.reconfigure(encoding='utf-8')
        sys.stderr.reconfigure(encoding='utf-8')
    elif hasattr(sys.stdout, 'buffer'):
        # 旧版本Python的替代方案，要求sys.stdout有buffer属性
        import codecs
        sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer)
        sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer)
    # 其他情况下不进行处理，使用系统默认编码
except Exception as e:
    print(f"设置编码时出错: {e}，将使用系统默认编码继续")

# 设置locale
try:
    locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
except:
    try:
        locale.setlocale(locale.LC_ALL, 'Chinese_China.utf8')
    except:
        try:
            locale.setlocale(locale.LC_ALL, '')
        except:
            pass

# 添加项目根目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, current_dir)

# 导入配置类
from app.config.app_config import AppConfig

# 设置是否为发布版本
IS_RELEASE = True  # 发布时设置为True

def setup_config():
    """设置应用程序配置"""
    # 获取配置实例
    config = AppConfig.get_instance()
    
    # 如果是发布版本，关闭Socket数据日志显示
    if IS_RELEASE:
        config.set_debug_enabled(False)
        config.set("debug", "verbose_logging", False)
    
    return config

def check_dependencies():
    """检查依赖是否已安装"""
    try:
        import PyQt5
        from PyQt5.QtWidgets import QComboBox, QTabWidget
        print("PyQt5已安装")
        return True
    except ImportError:
        print("错误: PyQt5未安装")
        print("请运行: pip install PyQt5==5.15.9")
        return False

def ensure_directories():
    """确保必要的目录和文件存在"""
    # 确保配置目录存在
    os.makedirs('app/config', exist_ok=True)
    
    # 确保组件目录存在
    os.makedirs('app/ui/components', exist_ok=True)
    
    # 确保UI目录存在
    os.makedirs('app/ui/windows', exist_ok=True)
    
    # 确保配置文件存在
    if not os.path.exists('app/config/default_config.py'):
        with open('app/config/default_config.py', 'w', encoding='utf-8') as f:
            f.write("""
# 默认配置
UI_WINDOW_WIDTH = 1200
UI_WINDOW_HEIGHT = 800
WEBSOCKET_DEFAULT_URL = "ws://localhost:8080"
AUDIO_DEFAULT_VOLUME = 0.8
""")
    
    # 确保theme.py存在
    if not os.path.exists('app/ui/theme.py'):
        with open('app/ui/theme.py', 'w', encoding='utf-8') as f:
            f.write("""
class Theme:
    # 颜色
    PRIMARY_COLOR = "#4a90e2"
    SECONDARY_COLOR = "#f5f5f5"
    SUCCESS_COLOR = "#5cb85c"
    WARNING_COLOR = "#f0ad4e"
    DANGER_COLOR = "#d9534f"
    INFO_COLOR = "#5bc0de"
    
    # 字体
    FONT_FAMILY = "Microsoft YaHei"
    FONT_SIZE_SMALL = 9
    FONT_SIZE_NORMAL = 10
    FONT_SIZE_LARGE = 12
    
    # 边距
    MARGIN_SMALL = 5
    MARGIN_NORMAL = 10
    MARGIN_LARGE = 15
    
    # 圆角
    BORDER_RADIUS = 3
""")
    
    # 创建必要的组件文件
    component_files = {
        'styled_button.py': """
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import Qt

class StyledButton(QPushButton):
    def __init__(self, text="", parent=None):
        super().__init__(text, parent)
        self.setStyleSheet('''
            QPushButton {
                background-color: #f0f0f0;
                border: 1px solid #ddd;
                border-radius: 4px;
                padding: 6px 12px;
                color: #333333;
                font-size: 12px;
            }
            QPushButton:hover {
                background-color: #e6e6e6;
                border-color: #ccc;
            }
            QPushButton:pressed {
                background-color: #d9d9d9;
            }
            QPushButton:disabled {
                background-color: #f8f8f8;
                color: #aaaaaa;
                border-color: #eaeaea;
            }
        ''')
""",
        'styled_line_edit.py': """
from PyQt5.QtWidgets import QLineEdit

class StyledLineEdit(QLineEdit):
    def __init__(self, text="", parent=None):
        super().__init__(text, parent)
        self.setStyleSheet('''
            QLineEdit {
                border: 1px solid #ddd;
                border-radius: 3px;
                padding: 5px;
                background-color: white;
            }
            QLineEdit:focus {
                border: 1px solid #4a90e2;
            }
        ''')
""",
        'styled_label.py': """
from PyQt5.QtWidgets import QLabel

class StyledLabel(QLabel):
    def __init__(self, text="", parent=None):
        super().__init__(text, parent)
        self.setStyleSheet('''
            QLabel {
                color: #333;
                font-weight: normal;
            }
        ''')
"""
    }
    
    for filename, content in component_files.items():
        filepath = os.path.join('app/ui/components', filename)
        if not os.path.exists(filepath):
            with open(filepath, 'w', encoding='utf-8') as f:
                f.write(content)
    
    # 确保__init__.py文件存在
    init_files = [
        'app/__init__.py',
        'app/ui/__init__.py',
        'app/ui/components/__init__.py',
        'app/ui/windows/__init__.py',
        'app/config/__init__.py'
    ]
    
    for init_file in init_files:
        if not os.path.exists(init_file):
            with open(init_file, 'w', encoding='utf-8') as f:
                f.write("# 自动生成的初始化文件\n")

def setup_logging():
    """配置日志"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.StreamHandler(),
            logging.FileHandler('app.log', encoding='utf-8')
        ]
    )
    logger = logging.getLogger(__name__)
    logger.info("正在启动AI直播助手...")

def main():
    """主函数"""
    # 检查依赖
    if not check_dependencies():
        sys.exit(1)
    
    # 确保必要的目录和文件存在
    ensure_directories()
    
    # 设置日志
    setup_logging()

    # 注册QTextCursor元类型，解决跨线程信号问题
    
    # 注册QTextCursor元类型，解决跨线程信号问题
    
    # 导入PyQt5相关模块
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtCore import QCoreApplication, Qt
    
    # 设置应用程序属性
    QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
    
    # 创建应用程序实例
    app = QApplication(sys.argv)
    app.setStyle("Fusion")  # 使用Fusion风格
    
    # 设置应用程序信息
    app.setApplicationName("AI直播助手")
    app.setApplicationVersion("3.0.0")
    app.setOrganizationName("AI直播助手")
    app.setOrganizationDomain("livelistener.com")
    
    # 获取日志记录器
    logger = logging.getLogger(__name__)
    
    # 设置应用程序配置
    config = setup_config()
    logger.info(f"应用程序配置已加载，调试模式: {config.is_debug_enabled()}")
    
    # 导入必要的模块
    try:
        from app.ui.windows.main_window import MainWindow
        from app.services.service_initializer import initialize_services
        from app.services.config_service_impl import ConfigService
        from app.services.websocket_service_impl import WebSocketService
        from app.services.comment_service_impl import CommentService
        from app.services.ai_service_impl import AIService
        from app.services.speech_service_impl import SpeechService
        from app.services.script_service_impl import ScriptService
        from app.services.audio_service_impl import AudioService
        from app.services.sync_service_impl import SyncService
        from app.services.flow_monitor_service_impl import FlowMonitorService
        from app.ui.theme import Theme
        from app.controllers.websocket_controller import WebSocketController
        from app.services.service_locator import ServiceLocator
        
        # 应用主题
        Theme.apply_theme(app)
        
        # 初始化基本服务（只初始化配置服务）
        logger.info("初始化基本服务...")
        initialize_basic_services(ConfigService)
        
        # 初始化剩余服务
        initialize_remaining_services(
            WebSocketService,
            CommentService,
            AIService,
            SpeechService,
            ScriptService,
            AudioService,
            SyncService,
            FlowMonitorService
        )
        
        # 初始化控制器（确保在服务初始化之后）
        logger.info("初始化控制器...")
        _initialize_controllers()
        
        # 创建主窗口（确保在控制器初始化之后）
        window = MainWindow()
        
        # 显示主窗口
        window.show()
        
        # 设置默认音频输出设备
        window.config_panel.audio_output_combo.setCurrentText("扬声器")
        
        # 设置音画同步状态（默认未开启）
        window.update_sync_status("未开启")
        
        # 默认选择中控标签页
        window.main_tabs.setCurrentIndex(0)
        
        logger.info("应用程序已启动")
        sys.exit(app.exec_())
    except Exception as e:
        logger.error(f"启动失败: {e}", exc_info=True)
        print(f"错误: {e}")
        input("按Enter键退出...")

def initialize_basic_services(config_service_cls):
    """
    初始化基本服务（只初始化配置服务）
    
    @param config_service_cls: 配置服务类
    """
    from app.services.service_locator import ServiceLocator
    from app.services.config_service import IConfigService
    
    # 清除现有服务
    ServiceLocator.clear()
    
    # 初始化配置服务
    config_service = config_service_cls()
    ServiceLocator.register(IConfigService, config_service)
    config_service.load_config()

def initialize_remaining_services(
    websocket_service_cls,
    comment_service_cls,
    ai_service_cls,
    speech_service_cls,
    script_service_cls,
    audio_service_cls,
    sync_service_cls,
    flow_monitor_service_cls
):
    """
    初始化剩余服务
    
    @param websocket_service_cls: WebSocket 服务类
    @param comment_service_cls: 评论服务类
    @param ai_service_cls: AI 服务类
    @param speech_service_cls: 语音服务类
    @param script_service_cls: 脚本服务类
    @param audio_service_cls: 音频服务类
    @param sync_service_cls: 音画同步服务类
    @param flow_monitor_service_cls: 流量监控服务类
    """
    from app.services.service_locator import ServiceLocator
    from app.services.config_service import IConfigService
    from app.services.websocket_service import IWebSocketService
    from app.services.comment_service import ICommentService
    from app.services.ai_service import IAIService
    from app.services.speech_service import ISpeechService
    from app.services.script_service import IScriptService
    from app.services.audio_service import IAudioService
    from app.services.sync_service import ISyncService
    from app.services.flow_monitor_service import IFlowMonitorService
    import logging
    
    logger = logging.getLogger(__name__)
    
    # 获取配置服务
    config_service = ServiceLocator.get(IConfigService)
    
    # 初始化 WebSocket 服务（确保先初始化它）
    try:
        websocket_service = websocket_service_cls()
        ServiceLocator.register(IWebSocketService, websocket_service)
        logger.info("WebSocket服务初始化成功")
    except Exception as e:
        logger.error(f"WebSocket服务初始化失败: {str(e)}")
        import traceback
        logger.error(traceback.format_exc())
    
    # 初始化评论服务
    comment_service = comment_service_cls()
    ServiceLocator.register(ICommentService, comment_service)
    
    # 初始化 AI 服务
    ai_service = ai_service_cls()
    ServiceLocator.register(IAIService, ai_service)
    
    # 初始化语音服务
    speech_service = speech_service_cls()
    ServiceLocator.register(ISpeechService, speech_service)
    
    # 初始化脚本服务
    script_service = script_service_cls()
    ServiceLocator.register(IScriptService, script_service)
    
    # 初始化音频服务
    audio_service = audio_service_cls()
    ServiceLocator.register(IAudioService, audio_service)
    
    # 初始化音画同步服务
    sync_service = sync_service_cls()
    ServiceLocator.register(ISyncService, sync_service)
    
    # 初始化流量监控服务
    flow_monitor_service = flow_monitor_service_cls()
    ServiceLocator.register(IFlowMonitorService, flow_monitor_service)
    
    # 设置服务之间的依赖关系
    # WebSocket 服务 -> 评论服务
    websocket_service = ServiceLocator.get(IWebSocketService)
    if websocket_service and hasattr(websocket_service, 'set_comment_service'):
        websocket_service.set_comment_service(comment_service)
    
    # 评论服务 -> AI 服务
    if hasattr(comment_service, 'set_ai_service'):
        logger.info("设置AI服务到评论服务")
        comment_service.set_ai_service(ai_service)
    
    # 脚本服务 -> 语音服务
    if hasattr(script_service, 'set_speech_service'):
        script_service.set_speech_service(speech_service)
    
    # AI服务 -> 语音服务
    if hasattr(ai_service, 'set_speech_service'):
        ai_service.set_speech_service(speech_service)
    
    # 配置服务到各个服务的配置
    _configure_services(config_service)
    
    # 设置事件监听器
    _setup_event_listeners()
    

def _configure_services(config_service):
    """
    配置所有服务
    
    @param config_service: 配置服务
    """
    from app.services.service_locator import ServiceLocator
    from app.services.websocket_service import IWebSocketService
    from app.services.ai_service import IAIService
    from app.services.speech_service import ISpeechService
    from app.services.script_service import IScriptService
    from app.services.audio_service import IAudioService
    from app.services.sync_service import ISyncService
    
    try:
        # 获取所有配置
        config = config_service.get_all_config()
        
        # 配置 WebSocket 服务
        websocket_service = ServiceLocator.get(IWebSocketService)
        if websocket_service and "websocket" in config:
            websocket_service.configure(config["websocket"])
        
        # 配置 AI 服务
        ai_service = ServiceLocator.get(IAIService)
        if ai_service and "ai" in config:
            ai_service.configure(config["ai"])
        
        # 配置语音服务
        speech_service = ServiceLocator.get(ISpeechService)
        if speech_service and "speech" in config:
            speech_service.configure(config["speech"])
        
        # 配置脚本服务
        script_service = ServiceLocator.get(IScriptService)
        if script_service and "script" in config:
            script_service.configure(config["script"])
        
        # 配置音频服务
        audio_service = ServiceLocator.get(IAudioService)
        if audio_service:
            # 配置音频服务
            if "audio" in config:
                audio_service.configure(config["audio"])
            
            # 配置TTS服务
            if "tts" in config:
                # 如果有TTS URL，则更新到音频服务
                if "url" in config["tts"]:
                    audio_service.configure({"tts_url": config["tts"]["url"]})
        
        # 配置音画同步服务
        sync_service = ServiceLocator.get(ISyncService)
        if sync_service and "sync" in config:
            sync_service.configure(config["sync"])
        
    except Exception as e:
        print(f"配置服务失败: {str(e)}")

def _setup_event_listeners():
    """
    设置事件监听器
    """
    from app.services.service_locator import ServiceLocator
    from app.services.websocket_service import IWebSocketService
    from app.services.comment_service import ICommentService
    from app.services.ai_service import IAIService
    
    # 获取服务
    websocket_service = ServiceLocator.get(IWebSocketService)
    comment_service = ServiceLocator.get(ICommentService)
    ai_service = ServiceLocator.get(IAIService)
    
    # 设置 WebSocket 服务的消息监听器
    # 注意：这里设置的监听器是处理WebSocket消息的第一条路径
    # 第二条路径是通过WebSocketController的_on_message方法和message_received信号
    # 两条路径都会调用comment_service.process_message，但CommentService内部有消息去重机制
    if websocket_service and comment_service:
        websocket_service.add_listener("message_received", lambda event: _on_websocket_message(event, comment_service))
    
    # 设置 AI 服务的分析完成监听器
    if ai_service and comment_service:
        ai_service.add_listener("comment_analyzed", lambda event: _on_ai_analysis_completed(event, comment_service))

def _on_websocket_message(event, comment_service):
    """处理 WebSocket 消息"""
    logging.info(f"收到WebSocket消息事件: {event.data.get('type', 'unknown')}")
    
    try:
        # 使用消息处理器处理消息 - 不再提供备用处理方式
        from app.services.message_processor import MessageProcessor
        processor = MessageProcessor.get_instance()
        message_id = processor.process_message(event.data, "websocket_event")
        if message_id:
            logging.info(f"WebSocket消息已处理，消息ID: {message_id}")
        else:
            logging.warning("WebSocket消息处理未完成，可能是重复消息或格式无效")
    except ImportError:
        # 消息处理器不可用，记录错误但不提供备用处理方式
        logging.error("消息处理器不可用，无法处理消息")
        logging.error("请确保MessageProcessor模块已正确安装和导入")
    except Exception as e:
        # 消息处理器处理失败，记录错误但不提供备用处理方式
        logging.error(f"处理WebSocket消息时出错: {str(e)}")
        import traceback
        logging.error(f"异常堆栈: {traceback.format_exc()}")

def _on_ai_analysis_completed(event, comment_service):
    """处理 AI 分析完成事件"""
    # 由于 CommentService 中没有 update_comment_analysis 方法，我们只记录事件
    logging.info(f"收到AI分析完成事件: {event.data}")
    
    # 获取评论ID和回复
    comment_id = event.data.get("comment_id", "")
    reply = event.data.get("reply", "")
    source = event.data.get("source", "unknown")
    
    logging.info(f"AI分析结果: ID={comment_id}, 来源={source}, 回复长度={len(reply) if reply else 0}")
    logging.info("AI分析事件处理完成")

def _initialize_controllers():
    """
    初始化并注册控制器
    """
    from app.services.service_locator import ServiceLocator
    from app.controllers.websocket_controller import WebSocketController
    from app.services.websocket_service import IWebSocketService
    import time
    import logging
    
    logger = logging.getLogger(__name__)
    
    # 确保WebSocket服务已经初始化好
    retry_count = 0
    max_retries = 5
    websocket_service = None
    
    while retry_count < max_retries:
        websocket_service = ServiceLocator.get(IWebSocketService)
        if websocket_service:
            logger.info("成功获取WebSocket服务")
            break
        
        logger.warning(f"WebSocket服务尚未初始化，等待中... (尝试 {retry_count + 1}/{max_retries})")
        time.sleep(0.2)  # 等待200毫秒
        retry_count += 1
    
    # 检查WebSocket服务是否可用
    if not websocket_service:
        logger.error("WebSocket服务不可用，控制器可能无法正常工作")
    
    # 初始化WebSocket控制器
    websocket_controller = WebSocketController()
    ServiceLocator.register(WebSocketController, websocket_controller)
    
    # 打印调试信息
    logger.info(f"WebSocket控制器初始化完成，WebSocket服务可用: {websocket_service is not None}")

if __name__ == "__main__":
    main() 